home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / toobin.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  16KB  |  646 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/toobin.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         2 16-bit words are used
  12.  
  13.         Word 1:
  14.             Bits  4-7  = priority of the image
  15.             Bits  0-3  = palette
  16.  
  17.         Word 2:
  18.             Bit  15    = vertical flip
  19.             Bit  14    = horizontal flip
  20.             Bits  0-13 = image index
  21.  
  22.  
  23.     Motion Object encoding
  24.     ----------------------
  25.         4 16-bit words are used
  26.  
  27.         Word 1:
  28.             Bit  15    = absolute/relative positioning (1 = absolute)
  29.             Bits  6-14 = Y position
  30.             Bits  3-5  = height in tiles
  31.             Bits  0-2  = width in tiles
  32.  
  33.         Word 2:
  34.             Bit  15    = vertical flip
  35.             Bit  14    = horizontal flip
  36.             Bits  0-13 = image index
  37.  
  38.         Word 3:
  39.             Bits 12-15 = priority (only upper 2 bits used)
  40.             Bits  0-7  = link to the next image to display
  41.  
  42.         Word 4:
  43.             Bits  6-15 = X position
  44.             Bits  0-3  = palette
  45.  
  46.  
  47.     Alpha layer encoding
  48.     --------------------
  49.         1 16-bit word is used
  50.  
  51.         Word 1:
  52.             Bit  12-15 = palette
  53.             Bit  11    = horizontal flip
  54.             Bits  0-10 = image index
  55.  
  56. ***************************************************************************/
  57.  
  58. #include "driver.h"
  59. #include "machine/atarigen.h"
  60. #include "vidhrdw/generic.h"
  61.  
  62. #define XCHARS 64
  63. #define YCHARS 48
  64.  
  65. #define XDIM (XCHARS*8)
  66. #define YDIM (YCHARS*8)
  67.  
  68.  
  69.  
  70. /*************************************
  71.  *
  72.  *    Globals we own
  73.  *
  74.  *************************************/
  75.  
  76. UINT8 *toobin_intensity;
  77. UINT8 *toobin_moslip;
  78.  
  79.  
  80.  
  81. /*************************************
  82.  *
  83.  *    Statics
  84.  *
  85.  *************************************/
  86.  
  87. static struct atarigen_pf_state pf_state;
  88. static UINT8 last_intensity;
  89.  
  90.  
  91.  
  92. /*************************************
  93.  *
  94.  *    Prototypes
  95.  *
  96.  *************************************/
  97.  
  98. static const UINT8 *update_palette(void);
  99.  
  100. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  101. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  102. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  103.  
  104. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  105. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  106.  
  107.  
  108.  
  109. /*************************************
  110.  *
  111.  *    Video system start
  112.  *
  113.  *************************************/
  114.  
  115. int toobin_vh_start(void)
  116. {
  117.     static struct atarigen_mo_desc mo_desc =
  118.     {
  119.         256,                 /* maximum number of MO's */
  120.         8,                   /* number of bytes per MO entry */
  121.         2,                   /* number of bytes between MO words */
  122.         2,                   /* ignore an entry if this word == 0xffff */
  123.         2, 0, 0xff,          /* link = (data[linkword] >> linkshift) & linkmask */
  124.         0                    /* render in reverse link order */
  125.     };
  126.  
  127.     static struct atarigen_pf_desc pf_desc =
  128.     {
  129.         8, 8,                /* width/height of each tile */
  130.         128, 64                /* number of tiles in each direction */
  131.     };
  132.  
  133.     /* reset statics */
  134.     last_intensity = 0;
  135.  
  136.     /* initialize the playfield */
  137.     if (atarigen_pf_init(&pf_desc))
  138.         return 1;
  139.  
  140.     /* initialize the motion objects */
  141.     if (atarigen_mo_init(&mo_desc))
  142.     {
  143.         atarigen_pf_free();
  144.         return 1;
  145.     }
  146.  
  147.     return 0;
  148. }
  149.  
  150.  
  151.  
  152. /*************************************
  153.  *
  154.  *    Video system shutdown
  155.  *
  156.  *************************************/
  157.  
  158. void toobin_vh_stop(void)
  159. {
  160.     atarigen_pf_free();
  161.     atarigen_mo_free();
  162. }
  163.  
  164.  
  165.  
  166. /*************************************
  167.  *
  168.  *    Playfield RAM write handler
  169.  *
  170.  *************************************/
  171.  
  172. WRITE_HANDLER( toobin_playfieldram_w )
  173. {
  174.     int oldword = READ_WORD(&atarigen_playfieldram[offset]);
  175.     int newword = COMBINE_WORD(oldword, data);
  176.  
  177.     if (oldword != newword)
  178.     {
  179.         WRITE_WORD(&atarigen_playfieldram[offset], newword);
  180.         atarigen_pf_dirty[offset / 4] = 1;
  181.     }
  182. }
  183.  
  184.  
  185.  
  186. /*************************************
  187.  *
  188.  *    Palette RAM write handler
  189.  *
  190.  *************************************/
  191.  
  192. WRITE_HANDLER( toobin_paletteram_w )
  193. {
  194.     int oldword = READ_WORD(&paletteram[offset]);
  195.     int newword = COMBINE_WORD(oldword, data);
  196.     WRITE_WORD(&paletteram[offset], newword);
  197.  
  198.     {
  199.         int red =   (((newword >> 10) & 31) * 224) >> 5;
  200.         int green = (((newword >>  5) & 31) * 224) >> 5;
  201.         int blue =  (((newword      ) & 31) * 224) >> 5;
  202.  
  203.         if (red) red += 38;
  204.         if (green) green += 38;
  205.         if (blue) blue += 38;
  206.  
  207.         if (!(newword & 0x8000))
  208.         {
  209.             red = (red * last_intensity) >> 5;
  210.             green = (green * last_intensity) >> 5;
  211.             blue = (blue * last_intensity) >> 5;
  212.         }
  213.  
  214.         palette_change_color((offset / 2) & 0x3ff, red, green, blue);
  215.     }
  216. }
  217.  
  218.  
  219.  
  220. /*************************************
  221.  *
  222.  *    Periodic scanline updater
  223.  *
  224.  *************************************/
  225.  
  226. void toobin_scanline_update(int scanline)
  227. {
  228.     int link = READ_WORD(&toobin_moslip[0]) & 0xff;
  229.  
  230.     /* update the playfield */
  231.     if (scanline == 0)
  232.     {
  233.         pf_state.hscroll = (READ_WORD(&atarigen_hscroll[0]) >> 6) & 0x3ff;
  234.         pf_state.vscroll = (READ_WORD(&atarigen_vscroll[0]) >> 6) & 0x1ff;
  235.         atarigen_pf_update(&pf_state, scanline);
  236.     }
  237.  
  238.     /* update the motion objects */
  239.     if (scanline < YDIM)
  240.         atarigen_mo_update(atarigen_spriteram, link, scanline);
  241. }
  242.  
  243.  
  244.  
  245. /*************************************
  246.  *
  247.  *    MO SLIP write handler
  248.  *
  249.  *************************************/
  250.  
  251. WRITE_HANDLER( toobin_moslip_w )
  252. {
  253.     COMBINE_WORD_MEM(&toobin_moslip[offset], data);
  254.     toobin_scanline_update(cpu_getscanline());
  255. }
  256.  
  257.  
  258.  
  259. /*************************************
  260.  *
  261.  *    Main refresh
  262.  *
  263.  *************************************/
  264.  
  265. void toobin_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  266. {
  267.     /* update the palette */
  268.     if (update_palette())
  269.         memset(atarigen_pf_dirty, 1, atarigen_playfieldram_size / 4);
  270.  
  271.     /* render the playfield */
  272.     memset(atarigen_pf_visit, 0, 128*64);
  273.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  274.  
  275.     /* render the motion objects */
  276.     atarigen_mo_process(mo_render_callback, bitmap);
  277.  
  278.     /* render the alpha layer */
  279.     {
  280.         const struct GfxElement *gfx = Machine->gfx[2];
  281.         int sx, sy, offs;
  282.  
  283.         for (sy = 0; sy < YCHARS; sy++)
  284.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  285.             {
  286.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  287.                 int code = data & 0x3ff;
  288.  
  289.                 /* if there's a non-zero code, draw the tile */
  290.                 if (code)
  291.                 {
  292.                     int color = (data >> 12) & 15;
  293.                     int hflip = data & 0x400;
  294.  
  295.                     /* draw the character */
  296.                     drawgfx(bitmap, gfx, code, color, hflip, 0, 8 * sx, 8 * sy, 0, TRANSPARENCY_PEN, 0);
  297.                 }
  298.             }
  299.     }
  300.  
  301.     /* update onscreen messages */
  302.     atarigen_update_messages();
  303. }
  304.  
  305.  
  306.  
  307. /*************************************
  308.  *
  309.  *    Palette management
  310.  *
  311.  *************************************/
  312.  
  313. static const UINT8 *update_palette(void)
  314. {
  315.     UINT16 al_map[16], pf_map[16], mo_map[16];
  316.     int intensity, i, j;
  317.  
  318.     /* compute the intensity and modify the palette if it's different */
  319.     intensity = 0x1f - (READ_WORD(&toobin_intensity[0]) & 0x1f);
  320.     if (intensity != last_intensity)
  321.     {
  322.         last_intensity = intensity;
  323.         for (i = 0; i < 256+256+64; i++)
  324.         {
  325.             int newword = READ_WORD(&paletteram[i*2]);
  326.             int red =   (((newword >> 10) & 31) * 224) >> 5;
  327.             int green = (((newword >>  5) & 31) * 224) >> 5;
  328.             int blue =  (((newword      ) & 31) * 224) >> 5;
  329.  
  330.             if (red) red += 38;
  331.             if (green) green += 38;
  332.             if (blue) blue += 38;
  333.  
  334.             if (!(newword & 0x8000))
  335.             {
  336.                 red = (red * last_intensity) >> 5;
  337.                 green = (green * last_intensity) >> 5;
  338.                 blue = (blue * last_intensity) >> 5;
  339.             }
  340.  
  341.             palette_change_color(i, red, green, blue);
  342.         }
  343.     }
  344.  
  345.     /* reset color tracking */
  346.     memset(mo_map, 0, sizeof(mo_map));
  347.     memset(pf_map, 0, sizeof(pf_map));
  348.     memset(al_map, 0, sizeof(al_map));
  349.     palette_init_used_colors();
  350.  
  351.     /* update color usage for the playfield */
  352.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  353.  
  354.     /* update color usage for the mo's */
  355.     atarigen_mo_process(mo_color_callback, mo_map);
  356.  
  357.     /* update color usage for the alphanumerics */
  358.     {
  359.         const unsigned int *usage = Machine->gfx[2]->pen_usage;
  360.         int offs, sx, sy;
  361.  
  362.         for (sy = 0; sy < YCHARS; sy++)
  363.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  364.             {
  365.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  366.                 int color = (data >> 12) & 0x000f;
  367.                 int code = data & 0x03ff;
  368.                 al_map[color] |= usage[code];
  369.             }
  370.     }
  371.  
  372.     /* rebuild the playfield palette */
  373.     for (i = 0; i < 16; i++)
  374.     {
  375.         UINT16 used = pf_map[i];
  376.         if (used)
  377.             for (j = 0; j < 16; j++)
  378.                 if (used & (1 << j))
  379.                     palette_used_colors[0x000 + i * 16 + j] = PALETTE_COLOR_USED;
  380.     }
  381.  
  382.     /* rebuild the motion object palette */
  383.     for (i = 0; i < 16; i++)
  384.     {
  385.         UINT16 used = mo_map[i];
  386.         if (used)
  387.         {
  388.             palette_used_colors[0x100 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  389.             for (j = 1; j < 16; j++)
  390.                 if (used & (1 << j))
  391.                     palette_used_colors[0x100 + i * 16 + j] = PALETTE_COLOR_USED;
  392.         }
  393.     }
  394.  
  395.     /* rebuild the alphanumerics palette */
  396.     for (i = 0; i < 16; i++)
  397.     {
  398.         UINT16 used = al_map[i];
  399.         if (used)
  400.             for (j = 0; j < 4; j++)
  401.                 if (used & (1 << j))
  402.                     palette_used_colors[0x200 + i * 4 + j] = PALETTE_COLOR_USED;
  403.     }
  404.  
  405.     return palette_recalc();
  406. }
  407.  
  408.  
  409.  
  410. /*************************************
  411.  *
  412.  *    Playfield palette
  413.  *
  414.  *************************************/
  415.  
  416. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  417. {
  418.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  419.     UINT16 *colormap = param;
  420.     int x, y;
  421.  
  422.     /* standard loop over tiles */
  423.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  424.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 127)
  425.         {
  426.             int offs = y * 128 + x;
  427.             int data1 = READ_WORD(&atarigen_playfieldram[offs * 4]);
  428.             int data2 = READ_WORD(&atarigen_playfieldram[offs * 4 + 2]);
  429.             int color = data1 & 0x000f;
  430.             int code = data2 & 0x3fff;
  431.  
  432.             /* mark the colors used by this tile */
  433.             colormap[color] |= usage[code];
  434.  
  435.             /* also mark unvisited tiles dirty */
  436.             if (!atarigen_pf_visit[offs]) atarigen_pf_dirty[offs] = 0xff;
  437.         }
  438. }
  439.  
  440.  
  441.  
  442. /*************************************
  443.  *
  444.  *    Playfield rendering
  445.  *
  446.  *************************************/
  447.  
  448. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  449. {
  450.     const struct GfxElement *gfx = Machine->gfx[0];
  451.     struct osd_bitmap *bitmap = param;
  452.     int x, y;
  453.  
  454.     /* standard loop over tiles */
  455.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  456.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 127)
  457.         {
  458.             int offs = y * 128 + x;
  459.  
  460.             /* update only if dirty */
  461.             if (atarigen_pf_dirty[offs])
  462.             {
  463.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 4]);
  464.                 int data2 = READ_WORD(&atarigen_playfieldram[offs * 4 + 2]);
  465.                 int color = data1 & 0x000f;
  466. /*                int priority = (data1 >> 4) & 3;*/
  467.                 int vflip = data2 & 0x8000;
  468.                 int hflip = data2 & 0x4000;
  469.                 int code = data2 & 0x3fff;
  470.  
  471.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, hflip, vflip, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  472.                 atarigen_pf_dirty[offs] = 0;
  473.             }
  474.  
  475.             /* track the tiles we've visited */
  476.             atarigen_pf_visit[offs] = 1;
  477.         }
  478.  
  479.     /* then blast the result */
  480.     x = -state->hscroll;
  481.     y = -state->vscroll;
  482.     copyscrollbitmap(bitmap, atarigen_pf_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_NONE, 0);
  483. }
  484.  
  485.  
  486.  
  487. /*************************************
  488.  *
  489.  *    Playfield overrendering
  490.  *
  491.  *************************************/
  492.  
  493. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  494. {
  495.     const struct GfxElement *gfx = Machine->gfx[0];
  496.     struct osd_bitmap *bitmap = param;
  497.     int x, y;
  498.  
  499.     /* standard loop over tiles */
  500.     for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  501.     {
  502.         int sy = (8 * y - state->vscroll) & 0x1ff;
  503.         if (sy >= YDIM) sy -= 0x200;
  504.  
  505.         for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 127)
  506.         {
  507.             int offs = y * 128 + x;
  508.             int data1 = READ_WORD(&atarigen_playfieldram[offs * 4]);
  509.             int priority = (data1 >> 4) & 3;
  510.  
  511.             /* overrender if there is a non-zero priority for this tile */
  512.             /* not perfect, but works for the most obvious cases */
  513.             if (priority)
  514.             {
  515.                 int data2 = READ_WORD(&atarigen_playfieldram[offs * 4 + 2]);
  516.                 int color = data1 & 0x000f;
  517.                 int vflip = data2 & 0x8000;
  518.                 int hflip = data2 & 0x4000;
  519.                 int code = data2 & 0x3fff;
  520.                 int sx = (8 * x - state->hscroll) & 0x1ff;
  521.                 if (sx >= XDIM) sx -= 0x400;
  522.  
  523.                 drawgfx(bitmap, gfx, code, color, hflip, vflip, sx, sy, clip, TRANSPARENCY_PENS, 0x000000ff);
  524.             }
  525.         }
  526.     }
  527. }
  528.  
  529.  
  530.  
  531. /*************************************
  532.  *
  533.  *    Motion object palette
  534.  *
  535.  *************************************/
  536.  
  537. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  538. {
  539.     const unsigned int *usage = Machine->gfx[1]->pen_usage;
  540.     UINT16 *colormap = param;
  541.     int hsize = (data[0] & 7) + 1;
  542.     int vsize = ((data[0] >> 3) & 7) + 1;
  543.     int code = data[1] & 0x3fff;
  544.     int color = data[3] & 0x000f;
  545.     int tiles = hsize * vsize;
  546.     UINT16 temp = 0;
  547.     int i;
  548.  
  549.     for (i = 0; i < tiles; i++)
  550.         temp |= usage[code++];
  551.     colormap[color] |= temp;
  552. }
  553.  
  554.  
  555.  
  556. /*************************************
  557.  *
  558.  *    Motion object rendering
  559.  *
  560.  *************************************/
  561.  
  562. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  563. {
  564.     const struct GfxElement *gfx = Machine->gfx[1];
  565.     struct osd_bitmap *bitmap = param;
  566.     struct rectangle pf_clip;
  567.  
  568.     /* extract data from the various words */
  569.     int absolute = data[0] & 0x8000;
  570.     int ypos = -(data[0] >> 6);
  571.     int hsize = (data[0] & 7) + 1;
  572.     int vsize = ((data[0] >> 3) & 7) + 1;
  573.     int vflip = data[1] & 0x8000;
  574.     int hflip = data[1] & 0x4000;
  575.     int code = data[1] & 0x3fff;
  576.     int xpos = data[3] >> 6;
  577.     int color = data[3] & 0x000f;
  578. //    int priority = (data[3] >> 4) & 3;
  579.  
  580.     /* adjust for height */
  581.     ypos -= vsize * 16;
  582.  
  583.     /* adjust position if relative */
  584.     if (!absolute)
  585.     {
  586.         xpos -= pf_state.hscroll;
  587.         ypos -= pf_state.vscroll;
  588.     }
  589.  
  590.     /* adjust the final coordinates */
  591.     xpos &= 0x3ff;
  592.     ypos &= 0x1ff;
  593.     if (xpos >= XDIM) xpos -= 0x400;
  594.     if (ypos >= YDIM) ypos -= 0x200;
  595.  
  596.     /* determine the bounding box */
  597.     atarigen_mo_compute_clip_16x16(pf_clip, xpos, ypos, hsize, vsize, clip);
  598.  
  599.     /* draw the motion object */
  600.     {
  601.         int tilex, tiley, screeny, screendx, screendy;
  602.         int screenx = xpos;
  603.         int starty = ypos;
  604.         int tile = code;
  605.  
  606.         /* adjust for h flip */
  607.         if (hflip)
  608.             screenx += (hsize - 1) * 16, screendx = -16;
  609.         else
  610.             screendx = 16;
  611.  
  612.         /* adjust for v flip */
  613.         if (vflip)
  614.             starty += (vsize - 1) * 16, screendy = -16;
  615.         else
  616.             screendy = 16;
  617.  
  618.         /* loop over the height */
  619.         for (tilex = 0; tilex < hsize; tilex++, screenx += screendx)
  620.         {
  621.             /* clip the x coordinate */
  622.             if (screenx <= clip->min_x - 16)
  623.             {
  624.                 tile += vsize;
  625.                 continue;
  626.             }
  627.             else if (screenx > clip->max_x)
  628.                 break;
  629.  
  630.             /* loop over the width */
  631.             for (tiley = 0, screeny = starty; tiley < vsize; tiley++, screeny += screendy, tile++)
  632.             {
  633.                 /* clip the y coordinate */
  634.                 if (screeny <= clip->min_y - 16 || screeny > clip->max_y)
  635.                     continue;
  636.  
  637.                 /* draw the sprite */
  638.                 drawgfx(bitmap, gfx, tile, color, hflip, vflip, screenx, screeny, clip, TRANSPARENCY_PEN, 0);
  639.             }
  640.         }
  641.     }
  642.  
  643.     /* overrender the playfield */
  644.     atarigen_pf_process(pf_overrender_callback, bitmap, &pf_clip);
  645. }
  646.